#!/bin/sh

e2e_test_install() {
  CLUSTER_NAME="$(get_sgcluster_name dbops-restart)"
  DBOPS_NAME="$(get_sgdbops_name restart)"

  kubectl create namespace "$CLUSTER_NAMESPACE"

  deploy_curl_pod "$CLUSTER_NAMESPACE"

  wait_pods_running "$CLUSTER_NAMESPACE" 1
}

reset_cluster() {
  local PODS_COUNT="${1:-2}"
  remove_cluster_if_exists "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"

  wait_until eval '[ "$(kubectl get pvc -n "$CLUSTER_NAMESPACE" --template "{{ .items | len }}")" = 0 ]'

  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" "$PODS_COUNT" \
    --set instanceProfiles[0].name=size-s \
    --set instanceProfiles[0].cpu=250m \
    --set instanceProfiles[0].memory=512Mi \

  wait_pods_running "$CLUSTER_NAMESPACE" "$((PODS_COUNT + 1))"
  wait_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
  switch_cluster_to_first "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"

  set_restarted_pods

  generate_mock_data "$CLUSTER_NAME"
  check_mock_data_samehost "$CLUSTER_NAME"
  if [ "$PODS_COUNT" -gt 1 ]
  then
    wait_until check_mock_data_replication "$CLUSTER_NAME"
  fi
}

check_restart_ran_successfully() {
  check_restart_is_running

  check_restart_completed
}

check_restart_is_running() {
  assert_dbops_running "$DBOPS_NAME" "$CLUSTER_NAMESPACE"
}

check_restart_completed() {
  assert_dbops_completion "$DBOPS_NAME" "$CLUSTER_NAMESPACE" "$((E2E_TIMEOUT * 2))"
}

check_restart_without_data() {
  check_restart true
}

trigger_cluster_require_restart() {
  local DATE="$(date +%s)"
  kubectl patch sgcluster -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" --type merge \
    -p "spec: { pods: { customEnv: { patroni: [{ name: REQUIRE_RESTART, value: '$DATE' }] } } }"
  kubectl wait sts --timeout "${E2E_TIMEOUT}s" -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" \
    --for jsonpath='{.spec.template.spec.containers[?(@.name == "patroni")].env[?(@.name == "REQUIRE_RESTART")].value}'="$DATE"
}

check_restart() {
  local SKIP_CHECK_DATA="$1"

  test -n "$RESTARTED_PODS"

  check_restart_is_running

  check_restart_completed

  local INITIAL_INSTANCES
  INITIAL_INSTANCES="$(kubectl get sgdbops -n "$CLUSTER_NAMESPACE" "$DBOPS_NAME" -o json)"
  INITIAL_INSTANCES="$(printf '%s' "$INITIAL_INSTANCES" | jq '.status.restart.initialInstances | length')"
  if printf '%s %s' "$RESTARTED_PODS" "$NOT_RESTARTED_PODS" | wc -w | grep -q "^$INITIAL_INSTANCES$"
  then
    success "Instances after restart match the initial instances in status ($INITIAL_INSTANCES)"
  else
    fail "Instances after restart ($(printf '%s %s' "$RESTARTED_PODS" "$NOT_RESTARTED_PODS" | wc -w)) do not match the initial instances in status ($INITIAL_INSTANCES)"
  fi

  local POD_CREATION_TIMESTAMP
  local POD
  for POD in $RESTARTED_PODS
  do
    POD_CREATION_TIMESTAMP="$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" --template='{{ .metadata.creationTimestamp }}')"
    POD_CREATION_TIMESTAMP="$(date -d "$POD_CREATION_TIMESTAMP" +%s)"
    if [ "$POD_CREATION_TIMESTAMP" -lt "$BEFORE_RESTART_DATE" ]
    then
      fail "Pod $POD was not restarted"
    else
      success "Pod $POD was restarted"
    fi
  done
  for POD in $NOT_RESTARTED_PODS
  do
    POD_CREATION_TIMESTAMP="$(kubectl get pod -n "$CLUSTER_NAMESPACE" "$POD" --template='{{ .metadata.creationTimestamp }}')"
    POD_CREATION_TIMESTAMP="$(date -d "$POD_CREATION_TIMESTAMP" +%s)"
    if [ "$POD_CREATION_TIMESTAMP" -lt "$BEFORE_RESTART_DATE" ]
    then
      success "Pod $POD was not restarted"
    else
      fail "Pod $POD was restarted"
    fi
  done

  if [ "$SKIP_CHECK_DATA" != true ]
  then
    wait_until check_mock_data_samehost "$CLUSTER_NAME"
    if [ "$INITIAL_INSTANCES" -ge 2 ]
    then
      wait_until check_mock_data_replication "$CLUSTER_NAME"
    fi
  fi
}

set_restarted_pods() {
  BEFORE_RESTART_DATE="$(date +%s)"
  RESTARTED_PODS="$1"
  NOT_RESTARTED_PODS="$2"
  if [ -z "$RESTARTED_PODS" ]
  then
    RESTARTED_PODS="$(kubectl get pod -n "$CLUSTER_NAMESPACE" -l "app=StackGresCluster,stackgres.io/cluster-name=$CLUSTER_NAME,stackgres.io/cluster=true" \
    --template '{{ range .items }}{{ printf "%s " .metadata.name }}{{ end }}')"
  fi
}
